
package com.dstz.form.util;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.support.rowset.SqlRowSet;
import org.springframework.jdbc.support.rowset.SqlRowSetMetaData;
import org.springframework.stereotype.Component;

import com.dstz.base.api.response.impl.ResultMsg;
import com.dstz.base.core.id.IdUtil;
import com.dstz.base.core.util.BeanUtils;
import com.dstz.base.core.util.ExceptionUtil;
import com.dstz.base.core.util.StringUtil;
import com.dstz.form.constants.BooleanConstants;
import com.dstz.form.constants.FieldsConstants;
import com.dstz.form.constants.SqlConstants;
import com.dstz.form.vo.SqlFieldsVO;

/**
 * 数据表元数据抽象类。
 * 用于读取数据库表的元数据信息。
 * 1.查询数据库中的表列表。
 * 2.取得表的详细数据。
 * 
 * @author xianggang
 *
 */
@Component
public class TableOperUtil {
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	/**
	 * 根据sql脚本,数据源 获取字段列表设置
	 * 
	 * @param sql
	 * @param dsKey
	 * @return List<TmSqlFieldVO>
	 * @author xianggang
	 * @date 2018年4月25日 下午4:20:55
	 */
	public ResultMsg<List<SqlFieldsVO>> getColumnModalBySql(String sql, String dsKey) {
		
		logger.info("根据sql脚本,数据源 获取字段列表设置,dsAlias:{},sql:{}", dsKey, sql);
		
		String tempTableName = "TEMP_TABLE_VIEW_SQL_" + IdUtil.getSuid();
		String dropViewSql = "drop table " + tempTableName;
		boolean isCreateTepTable = false;
		
		// 获取数据源的jdbcTemplate
		JdbcTemplate newJdbcTemplate = JdbcTemplateUtil.getJdbcTemplate(dsKey);
		
		try {
			
			// 创建一个临时表
			sql = createTempTable(sql, dsKey, tempTableName, newJdbcTemplate);
			
			// 到这里已经创建了表了
			isCreateTepTable = true;
			
			// 通过临时表 找到对应的字段属性
			Map<String, String> fieldCommentMap = getFieldCommentMap(tempTableName, newJdbcTemplate);
			
			// 通过sql获取字段列表
			List<SqlFieldsVO> list = getFieldList(sql, newJdbcTemplate, fieldCommentMap);
			
			// 删除临时表
			// newJdbcTemplate.execute(dropViewSql);
			
			return ResultMsg.SUCCESS(list);
		} catch (Exception e) {
			
			logger.error("通过sql获取字段列表失败,e:{}", ExceptionUtil.getRootErrorMseeage(e));
			
			// 删除零时表
			if (isCreateTepTable) {
				newJdbcTemplate.execute(dropViewSql);
			}
			
			return ResultMsg.ERROR("通过sql获取字段列表失败:" + ExceptionUtil.getRootErrorMseeage(e));
		}
	}
	
	// 通过sql获取字段列表
	private List<SqlFieldsVO> getFieldList(String sql, JdbcTemplate newJdbcTemplate,
	        Map<String, String> fieldCommentMap) {
		
		logger.info("通过sql获取字段列表,fieldCommentMap:{}", fieldCommentMap);
		
		SqlRowSet srs = newJdbcTemplate.queryForRowSet(sql);
		SqlRowSetMetaData srsmd = srs.getMetaData();
		List<SqlFieldsVO> list = new ArrayList<SqlFieldsVO>();
		// 列从1开始算
		for (int i = 1; i < srsmd.getColumnCount() + 1; i++) {
			String cn = srsmd.getColumnName(i);
			String ctn = srsmd.getColumnTypeName(i);
			SqlFieldsVO field = new SqlFieldsVO();
			field.setName(cn);// 字段name
			field.setAlign("c");
			field.setTableName(srsmd.getTableName(i));
			field.setExportAble(BooleanConstants.YES);
			field.setAddAble(BooleanConstants.YES);
			field.setEditAble(BooleanConstants.YES);
			field.setImportAble(BooleanConstants.YES);
			field.setSearchAble(BooleanConstants.YES);
			
			String columnLabel = srsmd.getColumnLabel(i);
			field.setFieldName(columnLabel);
			// 设置字段备注 并且 判断jo中是否含有该字段的备注
			if (fieldCommentMap.containsKey(columnLabel)) {
				field.setFieldDesc(fieldCommentMap.get(columnLabel));
			} else {
				field.setFieldDesc(columnLabel);
			}
			
			// 设置字段类型
			String dataType = JdbcTemplateUtil.getDataType(ctn);
			field.setDataType(dataType);
			
			// 设置默认属性
			field.setHidden(BooleanConstants.NO);
			if (field.getFieldName().endsWith("id") || field.getFieldName().endsWith("Id")) {
				field.setHidden(BooleanConstants.YES);
			}
			field.setControlType(FieldsConstants.TEXT_INPUT);
			
			// 判断是否是日期类型
			if (dataType.equals(SqlConstants.COLUMNTYPE_DATE)) {
				field.setControlType(FieldsConstants.DATEPICKER);
				field.setDateFormat("yyyy-MM-dd");
			}
			
			// 判断是否是日期类型
			if (dataType.equals(SqlConstants.COLUMNTYPE_DATE_TIME)) {
				field.setControlType(FieldsConstants.DATEPICKER);
				field.setDateFormat("yyyy-MM-dd HH:mm:ss");
			}
			
			field.setSn(i);
			list.add(field);
		}
		return list;
	}
	
	// // 通过临时表 找到对应的字段属性
	private Map<String, String> getFieldCommentMap(String tempTableName, JdbcTemplate newJdbcTemplate) {
		
		logger.info("通过临时表 找到对应的字段属性,tempTableName:{}", tempTableName);
		
		String showColumnSql = "show full columns from " + tempTableName;
		List<Map<String, Object>> queryForList = newJdbcTemplate.queryForList(showColumnSql);
		com.alibaba.fastjson.JSONArray fieldCommentJa = com.alibaba.fastjson.JSONArray
		        .parseArray(com.alibaba.fastjson.JSONArray.toJSONString(queryForList));
		// 将属性存入map当中 方便下面获取 {"name":"姓名","sex":"性别"}
		Map<String, String> fieldCommentMap = new HashMap<String, String>();
		for (int i = 0; i < fieldCommentJa.size(); i++) {
			com.alibaba.fastjson.JSONObject tempJo = fieldCommentJa.getJSONObject(i);
			if (BeanUtils.isNotEmpty(tempJo.get("Comment"))) {
				fieldCommentMap.put(tempJo.get("Field").toString(), tempJo.get("Comment").toString());
			}
		}
		return fieldCommentMap;
	}
	
	// 替换相关的特殊字符
	private String createTempTable(String sql, String dsAlias, String tempTableName, JdbcTemplate newJdbcTemplate) {
		sql = StringUtil.quotToStr(sql);
		sql = sql.replaceAll(QutoConstants.SINGLE_QUOTE, "'");
		
		sql = SqlUtil.getNoDataSql(sql);
		String viewSql = "create temporary table " + tempTableName + " as " + sql;
		
		logger.info("创表脚本 , sql:{}", sql);
		
		// 创建一个临时表
		newJdbcTemplate.execute(viewSql);
		
		logger.info("创表成功 ,dsAlias:{}", dsAlias);
		
		// sql = "select * from " + tempTableName;
		
		return sql;
	}
	
}
